﻿using System.Web.Http;
using SimpleInjector;
using Sustainalytics.Entities;
using Sustainalytics.DataLayer;
using System.Configuration.Abstractions;
using System.Collections.Generic;
using Sustainalytics.DataLayer.Shared;
using Sustainalytics.MongoDB.Extensions;
using Sustainalytics.Insights.BusinessLogic;
using Sustainalytics.Replication.Publisher;
using Sustainalytics.Claims;
using Sustainalytics.AwsS3.Client;

namespace Sustainalytics.Insights.Service
{
    public static class CompositionRoot
    {
        private static readonly Dictionary<string, string> serviceBusParams = new Dictionary<string, string>
                {
                        { "ConnectionString", ConfigurationManager.Instance.AppSettings["Microsoft.ServiceBus.ConnectionString"] },
                        { "RegionEndpoint", ConfigurationManager.Instance.AppSettings["Microsoft.ServiceBus.RegionEndpoint"] },
                        { "SessionId", ConfigurationManager.Instance.AppSettings["Microsoft.ServiceBus.SessionId"] },
                        { "TopicPath", ConfigurationManager.Instance.AppSettings["Microsoft.ServiceBus.TopicPath"] },
                };

        public static Container RegisterDependencies(HttpConfiguration config)
        {
            var container = new Container();

            container.Options.DefaultScopedLifestyle = new SimpleInjector.Lifestyles.AsyncScopedLifestyle();
            container.RegisterWebApiControllers(config);

            var clientPlatformConnectionString = ConfigurationManager.Instance.ConnectionStrings["ClientPlatform"].ConnectionString;

            var accessKey = ConfigurationManager.Instance.AppSettings["S3AccessKey"].ToString();
            var secretAccessKey = ConfigurationManager.Instance.AppSettings["S3SecretAccessKey"].ToString();
            var serviceEndPoint = ConfigurationManager.Instance.AppSettings["S3ServiceEndPoint"].ToString();

            container.RegisterMisc(serviceBusParams, accessKey, secretAccessKey, serviceEndPoint);

            container.RegisterCollections(
                clientPlatformConnectionString);

            container.RegisterRepositories(clientPlatformConnectionString);

            container.RegisterBussinessLogic(clientPlatformConnectionString);

            container.Verify();

            return container;
        }

        private static void RegisterRepositories(this Container container,
           string clientPlatformConnectionString)
        {
            container.Register(typeof(IHelperRepository), () => new InsightRepository(clientPlatformConnectionString));
            container.Register(typeof(IInsightRepository), () => new InsightRepository(clientPlatformConnectionString));
        }

        private static void RegisterCollections(this Container container,
           string clientPlatformConnectionString)
        {
            container.Register(typeof(IRepositoryCollection<Insight>), () => new RepositoryCollection<Insight>(clientPlatformConnectionString));
        }

        private static void RegisterBussinessLogic(this Container container,
            string clientPlatformConnectionString)
        {
            container.Register(() => MongoFactory.GetCollectionFromDatabase<ResultOutput>(clientPlatformConnectionString));

            container.Register(typeof(IInsightBussinesLogic), () => new InsightsBussinesLogic(
                container.GetInstance<IInsightRepository>(), container.GetInstance<ServiceBusPublisher>()));
        }

        private static void RegisterMisc(
            this Container container,
            Dictionary<string, string> serviceBusParams, string accessKey, string secretAccessKey, string serviceEndPoint
            )
        {
            container.Register(() => MongoFactory.GetConnectionStrings());
            container.RegisterSingleton(typeof(IClaimsChecker), () => new ClaimsChecker());
            container.RegisterSingleton(() => { return new ServiceBusPublisher(serviceBusParams); });
            container.RegisterSingleton(typeof(IS3Client), () => new S3Client(new S3ClientSettings()
            {
                AccessKey = accessKey,
                SecretAccessKey = secretAccessKey,
                ServiceEndPoint = serviceEndPoint,
            }));
        }
    }
}
